# -*- shell-script -*-

# 30device-tree - device-tree related lscfg routines.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 2003, 2004, 2005

# Maintained by Martin Schwenke <martins@au.ibm.com>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    
# $Id: 30device-tree,v 1.1 2006/04/11 18:38:29 emunson Exp $

[ -f "${db_bus_dt_dir}/model" ] || return 0

######################################################################

get_cpus ()
{
    if [ -d "${db_bus_dt_dir}/cpus" ] ; then
	if [ -f "${db_bus_dt_dir}/cpus/smp-enabled" ] ; then
	    echo "Multiple Processor"
	else
	    echo "Uni-Processor"
	fi
    else
	get_cpus_basic
    fi
}

#---------------------------------------------------------------------

dt_platform_specific_header ()
{
    local node="$1"
    local prop="$2"
    local label="$3"

    local p="${node}/${prop}"
    if [ -f "$p" ] ; then
	local t
	read t <"$p"
	echo "    ${label}:  ${t}"
    fi
}

#---------------------------------------------------------------------

dt_platform_specific_vpd_line ()
{
    local k="$1"
    local v="$2"

    case "$k" in
	CI) lscfg_render_vpd_value "$k" "$v" "Controlling CEC ID"          ;;
	RD) lscfg_render_vpd_value "$k" "$v" "Power Domain ID"             ;;
	RM) lscfg_render_vpd_value "$k" "$v" "ROM Level.(alterable)"       ;;

	Y?) lscfg_render_vpd_value "$k" "$v" "System Info Specific.(${k})" ;;

	*)  lscfg_render_vpd_line  "$k" "$v";;
    esac
}

# FIXME: The YL handling here is a bad hack, but is easier than
# parsing the ibm,loc-code prop.  Also the generation of
# "Version=RS6K" is hardcoded and needs to be looked at.
dt_platform_specific_vpd ()
{
    local vpd_dir="$1"
    local nodebase="$2"

    local vpd_fields    
    vpd_fields_list_hook "$vpd_dir"

    local k vpd_value yl
    for k in $vpd_fields ; do
	case "$k" in
	    FC) echo ;; 
	    AX) :    ;;
	    *)
		vpd_field_get "$vpd_dir" "$k"
		case "$k" in
		    DS) printf '      %-16s:\n' "$vpd_value" ;;
		    YL) [ "$nodebase" = "/" ] && yl="$vpd_value"
			dt_platform_specific_vpd_line "${k%.*}" "$vpd_value"
			;;
		    *)  dt_platform_specific_vpd_line "${k%.*}" "$vpd_value" ;;
		esac
	esac
    done

    [ -n "$yl" ] && echo "      Physical Location: ${yl}"
}

dt_platform_specific_vpd_all ()
{
    local node="$1"
    local nodebase="$2"

    local vpd_subdirs
    vpd_subdirs_list_hook "$node"
    local vpd_dir
    for vpd_dir in $vpd_subdirs ; do
	dt_platform_specific_vpd "$vpd_dir" "$nodebase"
    done
}

dt_platform_specific_node ()
{
    local node="$1"
    local nodebase="$2"
    local ax="$3"

    if $first ; then
	echo
	echo "  PLATFORM SPECIFIC"
    fi

    echo
	
    local nodename
    read nodename <"${node}/name"
    echo "  Name:  ${nodename}"

    dt_platform_specific_header "$node" "model" "Model"
    echo "    Node:  ${nodebase}"
    
    if [ -f "${node}/device_type" ] &&
	[ "$nodename" != "$(cat ${node}/device_type)" ] ; then
	dt_platform_specific_header "$node" "device_type" "Device Type"
    fi
    
    local loc="${node}/ibm,loc-code"
    if [ "$nodebase" != "/" -a -f "$loc" ] ; then
	echo "    Physical Location: $(cat ${loc})"
    fi
    
    if $dovpd && [ -z "$ax" ] ; then
	if node_contains_dynamic_vpd "$node" ; then
	    should_show_dynamic_vpd && \
		dt_platform_specific_vpd_all "$node" "$nodebase"
	else
	    dt_platform_specific_vpd_all "$node" "$nodebase"
	fi
    fi

    first=false
}

dt_platform_specific_node_maybe ()
{
    local node="$1"

    # This only checks the first VPD subnode, but that's OK here.
    local vpd_dir
    vpd_dir_set_hook "$node"
    
    local vpd_value
    vpd_field_get "$vpd_dir" "AX"
    local ax="$vpd_value"

    local nodebase="${node##*/}" # basename
    if [ -z "$nodebase" -o "$nodebase" = "." ] ; then
	nodebase="/"
    fi
    
    if [ -n "$name" ] ; then
	case "$name" in
	    mem*)
		case "$nodebase" in
		    *memory-module*)
			dt_platform_specific_node \
			    "$node" "$nodebase" "$ax"
			;;
		    esac
		;;
	    *)
		case "$ax" in
		    $name)
			dt_platform_specific_node \
			    "$node" "$nodebase" "$ax"
			;;
		esac
		;;
	esac
    else
	case "$nodebase" in
	    (memory@*) : ;;
	    *)
		dt_platform_specific_node \
		    "$node" "$nodebase" "$ax"
		    ;;
	esac
    fi
}

do_platform_specific_section ()
{
    local first=true

    # 1. This works with busybox's version of find.
    # 2. This could be done more efficiently, but this is easy to maintain.
    local excludes i t
    for i in IBM,sp ibm,serial \
	aliases chosen options packages rtas sd st vdevice \
	"reserved@[^/]*" "rtc@[^/]*" "vty@[^/]*" ; do
      t="/${i}\$|/${i}/"
      [ -n "$excludes" ] && t="|${t}"
      excludes="${excludes}${t}"
    done

    find "${db_bus_dt_dir}/." -type d |
    egrep -v "$excludes" |
    sort |
    while read node ; do
	if [ -f "${node}/name" -a \
	     \( -f "${node}/model" -o \
		-f "${node}/device_type" -o \
		-f "${node}/ibm,loc-code" \) ] ;then
	    dt_platform_specific_node_maybe "$node"
	fi
    done
}
